package com.wujian.love.study.thread;

import java.util.concurrent.*;

/**
 * @ClassName: Memoizer
 * @Description:
 * @Author: wuj
 * @Date: 2021-03-09 09:56
 **/
public class Memoizer<A,V> implements Computable<A,V> {

    /**
     * Future代表的是异步执行的结果，意思是当异步执行结束之后，返回的结果将会保存在Future中。
     * 核心思想:让主线程将原来需要同步等待的这段时间用来做其他的事情
     *
     * 使用场景:1. 计算密集场景。2. 处理大数据量。3. 远程方法调用等
     */

    private final ConcurrentHashMap<A, Future<V>> cache = new ConcurrentHashMap<A,Future<V>>();

    private final Computable<A,V> c;


    public  Memoizer(Computable<A,V> c){
        this.c = c;
    }

    @Override
    public V computer(final A arg) throws InterruptedException {
        while (true){
            Future<V> f = cache.get(arg);

            if(f == null){
                //线程的创建，
                //我们常用的就是继承Thread或者实现Runnable，
                //但其实线程的创建不止这两种方法，还有一种方法就是带有返回值的线程创建Callable<V>
                //需要创建一个FutureTask对象，并传入一个Callable实现类对象，才能使用Thread.start()方法启动线程
                Callable<V> eval = new Callable<V>() {
                    @Override
                    public V call() throws Exception {
                        return c.computer(arg);
                    }
                };


                FutureTask<V> ft = new FutureTask<V>(eval);
                //原子方法
                //如果 Key 不存在或者对应的值是 null，
                // 则将 Value 设置进去，然后返回 null；否则只返回 Map 当中对应的值，而不做其他操作。
                f = cache.putIfAbsent(arg,ft);
                if(f == null){
                    f= ft;
                    ft.run();
                }
            }

            try {
                return f.get();
            }catch (CancellationException e){
                cache.remove(arg,f);
            }catch (ExecutionException e){
                System.out.println(e.getCause().getMessage());
            }
        }

    }





}
